﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Security;
using EventPlanner.DAL;
using EventPlanner.Models;
using EventPlanner.Performance;

namespace EventPlanner.Controllers
{
    [CompressFilter(Order = 1)]
    [OutputCache(Duration = 60, VaryByParam = "None")]
    [CacheFilter(Duration = 60, Order=2)]
    public class EventoController : Controller
    {
        private IEventPlannerContext db;


        public EventoController()
        {
            this.db = new EventPlannerContext();
        }

        /* EventoController(context): constructor utilizado para realizar los tests sobre el controlador(EventoController) */

        public EventoController(IEventPlannerContext context)
        {
            this.db = context;
        }
        
        //
        // GET: /Evento/

        /* ListaParticipante: consulta la base de datos y muestra una tabla con todos los eventos disponibles */

        public ViewResult ListaParticipante(String searchString)
        {
            var eventos = from s in db.Eventos
                           select s;
            if (!String.IsNullOrEmpty(searchString))
            {
                 eventos = eventos.Where(s => s.Nombre.ToUpper().Contains(searchString.ToUpper()) 
                                        || s.Descripcion.ToUpper().Contains(searchString.ToUpper()));
            }
            return View(eventos.ToList());
        }

        /* ListaUsuario: consulta la base de datos y muestra una tabla con todos eventos creados por el usuario */

        [Authorize]
        public ViewResult ListaUsuario(String searchString)
        {
            String UsuarioActual = db.GetUsuarioActual();
            Cuenta cuenta = db.Cuentas.Find(UsuarioActual);

            var eventos = from s in cuenta.Eventos
                          select s;
            if (!String.IsNullOrEmpty(searchString))
            {
                eventos = eventos.Where(s => s.Nombre.ToUpper().Contains(searchString.ToUpper()));
            }
            return View(eventos.ToList());
        }

        //
        // GET: /Evento/DetallesUsuario/5

        /* DetallesUsuario: muestra todos los detalles de un evento en particular creado por el usuario*/

        [Authorize]
        [CacheFilter(Duration = 60)]
        public ActionResult DetallesUsuario(int id)
        {
            String UsuarioActual = db.GetUsuarioActual();
            Cuenta cuenta = db.Cuentas.Find(UsuarioActual);
            Evento evento = db.Eventos.Find(id);
            if (cuenta.Eventos.Contains(evento))
            {
                Organizador organiza = db.Organizadores.Find(evento.OrganizadorID);
                ViewBag.NomOrganizador = organiza.Nombre;
                return View(evento);
            }
            else
            {
                return RedirectToAction("Mensaje_Acceso_denegado", "Autorizacion", new {msj="Evento/DetallesUsuario/"+id });
            }
        }

        //
        // GET: /Evento/DetallesParticipante/5

        /* DetallesParticipante: muestra detalles de un evento en particular al participante interesado */


        public ActionResult DetallesParticipante(int id)
        {
            Evento evento = db.Eventos.Find(id);
            Organizador organiza = db.Organizadores.Find(evento.OrganizadorID);
            ViewBag.NomOrganizador = organiza.Nombre;
            return View(evento);
        }

        /* AgregarParticipante: rutina utilizada cuando el usuario, dueño de una cuenta, agrega un participante
         * a un evento creado por él.*/

        public ActionResult AgregarParticipante(int id_evento)
        {
            return RedirectToAction("Inscripcion", "Participante", new { id_evento });
        }

        /* VerParticipantes: se utiliza cuando un usuario logueado desea ver los participantes inscriptos
         * en un evento en particular, creado por él.*/

        [Authorize]
        public ActionResult VerParticipantes(int id_evento)
        {
            return RedirectToAction("VerParticipantes", "Participante", new { id_evento });
        }

        /* EnviarInvitaciones: permite elegir contactos, a los cuales se le enviará invitaciones 
         * al evento correspondiente.*/

        [Authorize]
        public ActionResult EnviarInvitaciones(int id_evento)
        {
            return RedirectToAction("EnviarInvitaciones", "Invitaciones", new { id_evento });
        }

        //
        // GET: /Evento/Crear

        /* Crear: crea un evento nuevo en la base de datos y lo agrega en la cuenta del usuario. */

        [Authorize]
        public ActionResult Crear()
        {
            PopulateTipoEntradaDropDownList();
            PopulateOrganizadoresDropDownList();
            return View();
        }

        //
        // POST: /Evento/Crear

        [HttpPost]
        public ActionResult Crear(Evento evento)
        {
            if (ModelState.IsValid)
            {
                String UsuarioActual = db.GetUsuarioActual();
                evento.NombreCreador = UsuarioActual;
                var cuenta = db.Cuentas.Find(UsuarioActual);
                cuenta.Eventos.Add(evento);
                db.Eventos.Add(evento);
                db.SaveChanges();
                return RedirectToAction("ListaUsuario");  
            }
            PopulateTipoEntradaDropDownList(evento.TipoEntrada);
            PopulateOrganizadoresDropDownList(evento.OrganizadorID);

            return View(evento);
        }
        
        //
        // GET: /Evento/Editar/5

        /* Editar: modifica los datos correspondientes a un evento en la base de datos. */

        [Authorize]
        public ActionResult Editar(int id)
        {
            MembershipUser UsuarioActual = Membership.GetUser();
            Cuenta cuenta = db.Cuentas.Find(UsuarioActual.UserName);
            Evento evento = db.Eventos.Find(id);
            if (cuenta.Eventos.Contains(evento))
            {
                PopulateTipoEntradaDropDownList(evento.TipoEntrada);
                PopulateOrganizadoresDropDownList(evento.OrganizadorID);
                return View(evento);
            }
            else
            {
                return RedirectToAction("Mensaje_Acceso_denegado", "Autorizacion", new { msj = "Evento/Editar/" + id });
            }
        }

        //
        // POST: /Evento/Editar/5

        [HttpPost]
        public ActionResult Editar(Evento evento)
        {
            if (ModelState.IsValid)
            {
                Evento ev = db.Eventos.Find(evento.EventoID);
                if (TryUpdateModel<Evento>(ev))
                {
                    db.SaveChanges();
                    return RedirectToAction("ListaUsuario");
                }
            }
            PopulateTipoEntradaDropDownList(evento.TipoEntrada);
            PopulateOrganizadoresDropDownList(evento.OrganizadorID);
            return View(evento);
        }

        //
        // GET: /Evento/Eliminar/5

        /* Eliminar: borra un evento de la base de datos permanentemente. */

        [Authorize]
        public ActionResult Eliminar(int id)
        {
            MembershipUser UsuarioActual = Membership.GetUser();
            Cuenta cuenta = db.Cuentas.Find(UsuarioActual.UserName);
            Evento evento = db.Eventos.Find(id);
            if (cuenta.Eventos.Contains(evento))
            {
                return View(evento);
            }
            else
            {
                return RedirectToAction("Autenticacionfallida", "Autenticacion", new { msj = "Evento/Eliminar/" + id });
            }
        }

        //
        // POST: /Evento/Eliminar/5

        [HttpPost, ActionName("Eliminar")]
        public ActionResult EliminacionConfirmada(int id)
        {
            Evento evento = db.Eventos.Find(id);
            db.Eventos.Remove(evento);
            db.SaveChanges();
            return RedirectToAction("ListaUsuario");
        }

        /* PopulateTipoEntradaDropDownList: rutina para llenar la lista desplegable de tipo de entradas
         * y seleccion de una. */

        private void PopulateTipoEntradaDropDownList(object selectedTipoEntrada = null)
        {
            List<SelectListItem> items = new List<SelectListItem>();
            items.Add(new SelectListItem{Text="Entrada gratuita"});
            items.Add(new SelectListItem { Text = "Entrada con costo" });
            items.Add(new SelectListItem{Text="Entrada VIP"});
            ViewBag.TipoEntrada = new SelectList(items, "Text", "Text", selectedTipoEntrada);
        }

        /* PopulateOrganizadoresDropDownList: rutina para llenar la lista desplegable con los organizadores. */

        private void PopulateOrganizadoresDropDownList(object selectedOrganizador = null)
        {
            var organizadoresQuery = from d in db.Organizadores
                                   orderby d.Nombre
                                   select d;
            ViewBag.OrganizadorID = new SelectList(organizadoresQuery, "OrganizadorID", "Nombre", selectedOrganizador);
        }

        protected override void Dispose(bool disposing)
        {
            if (db is IDisposable)
            {
                ((IDisposable)db).Dispose();
            }
            base.Dispose(disposing);
        }
    }
}